[slug].vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <script lang='ts' setup>
  2. import { Api } from '@/api/model/url'
  3. import { useCommonStore } from '@/stores/modules/common'
  4. const config = useRuntimeConfig()
  5. const { apiBaseSiteUrl } = config.public
  6. const route = useRoute()
  7. const detail = ref<any>({})
  8. const tabValue = ref('blog')
  9. const isHasCatalogue = ref(true)
  10. const options = ref([
  11. {
  12. label: 'Read Blog',
  13. value: 'blog',
  14. },
  15. {
  16. label: 'Preview Catalog',
  17. value: 'catalog',
  18. },
  19. ])
  20. const slug = route.params.slug
  21. const { data, pending, error, refresh } = await useAsyncData(
  22. 'blog-detail',
  23. () =>
  24. $fetch(`${apiBaseSiteUrl}${Api.BlogDetail}`, { params: { slug } }),
  25. )
  26. const seoData = data.value?.result
  27. // 把createTime和updateTime转换为ISO格式
  28. if (seoData?.createTime)
  29. seoData.createTime = new Date(seoData.createTime).toISOString()
  30. if (seoData?.updateTime)
  31. seoData.updateTime = new Date(seoData.updateTime).toISOString()
  32. if (!seoData?.relatedCatalogue)
  33. isHasCatalogue.value = false
  34. detail.value = seoData
  35. useHead({
  36. title: detail.value?.metaTitle,
  37. meta: [
  38. {
  39. name: 'description',
  40. content: detail.value?.metaDescribe,
  41. },
  42. {
  43. property: 'og:title',
  44. content: detail.value?.metaTitle,
  45. },
  46. {
  47. property: 'og:description',
  48. content: detail.value?.metaDescribe,
  49. },
  50. {
  51. property: 'og:image',
  52. content: detail.value?.thumbnailUrl,
  53. },
  54. {
  55. property: 'og:url',
  56. content: `${apiBaseSiteUrl}/blog/${slug}`,
  57. },
  58. {
  59. property: 'og:type',
  60. content: 'website',
  61. },
  62. {
  63. property: 'twitter:title',
  64. content: detail.value?.metaTitle,
  65. },
  66. {
  67. property: 'twitter:description',
  68. content: detail.value?.metaDescribe,
  69. },
  70. {
  71. property: 'twitter:site',
  72. content: `${apiBaseSiteUrl}/blog/${slug}`,
  73. },
  74. {
  75. property: 'twitter:image',
  76. content: detail.value?.thumbnailUrl,
  77. },
  78. {
  79. property: 'twitter:card',
  80. content: 'summary_large_image',
  81. },
  82. ],
  83. script: [
  84. // JSON-LD
  85. {
  86. type: 'application/ld+json',
  87. children: JSON.stringify({
  88. datePublished: detail.value?.createTime,
  89. dateModified: detail.value?.updateTime,
  90. }),
  91. },
  92. ],
  93. link: [
  94. {
  95. rel: 'canonical',
  96. href: `${apiBaseSiteUrl}/blog/${slug}`,
  97. },
  98. ],
  99. })
  100. const { openLoginAndDownloadModal } = useLoginAndDownLoadModal()
  101. async function clickLoginAndDownload(item: any) {
  102. try {
  103. const commonStore = useCommonStore()
  104. commonStore.setDownloadCatalog(item)
  105. const { status } = await openLoginAndDownloadModal()
  106. if (status)
  107. location.reload()
  108. }
  109. catch (error) {
  110. console.log(error)
  111. }
  112. }
  113. </script>
  114. <template>
  115. <div class="blog-detail">
  116. <div class="bg-#F3F4FB ">
  117. <div class="pt-175px pb-110px w-1200-auto flex px-60px">
  118. <img :src="detail?.thumbnailUrl" :alt="detail?.thumbnailAlt" srcset="" class="w-410px h-256px b-rd-10px object-cover mr-40px">
  119. <div class="flex-1 text-left">
  120. <div class="b-rd-400px left-10px text-center w-138px h-32px lh-32px bg-#fff/50 backdrop-blur-20px b-1px b-solid b-#fff/60 text-#9B6CFF text-14px mb-20px">
  121. {{ detail.category_dictText }}
  122. </div>
  123. <h1
  124. class="!mb-20px fw-800 text-40px ls-2 text-#333 line-clamp-2 lh-50px custom-title-font"
  125. >
  126. {{ detail.contentTitle }}
  127. </h1>
  128. <div class="text-16px text-#999 lh-24px">
  129. {{ detail.contentSubhead }}
  130. </div>
  131. </div>
  132. </div>
  133. </div>
  134. <div class="w-1200-auto flex pt-30px">
  135. <div class="w-840px mr-60px">
  136. <div v-if="isHasCatalogue">
  137. <el-segmented v-model="tabValue" :options="options">
  138. <template #default="scope">
  139. <div>
  140. <div>{{ scope.item.label }}</div>
  141. </div>
  142. </template>
  143. </el-segmented>
  144. </div>
  145. <div v-show="tabValue === 'blog'" class="mt-30px content-detail custom-html" v-html="detail.content" />
  146. <div v-show="tabValue === 'catalog'" class="mt-30px">
  147. <iframe
  148. :src="`${detail?.relatedCatalogue?.viewPdf}#view=FitH&toolbar=0&scrollbar=0&navpanes=0`"
  149. allowfullscreen
  150. width="100%"
  151. height="1200px"
  152. style="border: none"
  153. >
  154. 您的浏览器不支持iframe,请使用现代浏览器查看PDF。
  155. </iframe>
  156. </div>
  157. </div>
  158. <div class="flex-1">
  159. <div v-if="isHasCatalogue" class="pos-relative mb-40px">
  160. <img :src="detail?.relatedCatalogue?.coverImg" :alt="detail?.relatedCatalogue?.coverAlt" srcset="" class="w-375px h-240px b-rd-10px object-cover">
  161. <h4
  162. class="!mb-15px !mt-30px fw-800 text-24px text-#333 line-clamp-2"
  163. >
  164. {{ detail?.relatedCatalogue?.title }}
  165. </h4>
  166. <div class="text-14px text-#999 lh-22px line-clamp-2 mb-20px">
  167. {{ detail?.relatedCatalogue?.subhead }}
  168. </div>
  169. <el-button class="!bg-#9B6CFF !text-#fff !b-#9B6CFF !b-rd-380px text-14px fw-bold !h-32px px-20px" @click="clickLoginAndDownload(detail?.relatedCatalogue)">
  170. Download Catalog
  171. </el-button>
  172. </div>
  173. <div class="px-40px pt-34px bg-#E7EAFF b-rd-10px text-center custom-main">
  174. <div class="text-#333 fw-500">
  175. Sign in for exclusive trending product catalogs!
  176. </div>
  177. <el-button class="mt-20px !bg-#fff !text-#9B6CFF !w-160px !h-40px !b-0px !b-rd-200px" round>
  178. <nuxt-link :to="{ name: 'contact' }">
  179. Sign In
  180. </nuxt-link>
  181. </el-button>
  182. </div>
  183. </div>
  184. </div>
  185. <common-block-blog class="!pb-0" />
  186. <AppFooter />
  187. </div>
  188. </template>
  189. <style lang='less' scoped>
  190. .el-segmented {
  191. --el-segmented-item-selected-color: #fff;
  192. --el-segmented-item-selected-bg-color: #9B6CFF;
  193. --el-border-radius-base: 16px;
  194. --el-segmented-bg-color: #F9FAFB;
  195. --el-segmented-color: #333;
  196. width: 100%;
  197. height: 68px;
  198. line-height: 68px;
  199. border-radius: 300px!important;
  200. overflow: hidden;
  201. padding: 0;
  202. ::v-deep .el-segmented__group {
  203. .el-segmented__item-selected,.el-segmented__item{
  204. border-radius: 300px!important;
  205. overflow: hidden;
  206. .el-segmented__item-label{
  207. font-size: 18px;
  208. }
  209. }
  210. }
  211. }
  212. .blog-detail {
  213. ::v-deep(.content-detail) {
  214. font-family: sans-serif;
  215. h2 {
  216. font-size: 1.5em;
  217. font-family: "CustomTitleFont";
  218. margin-top: 1em !important;
  219. margin-bottom: 1em !important;
  220. font-weight: bold;
  221. }
  222. h3 {
  223. display: block;
  224. font-size: 1.17em;
  225. margin-block-start: 1em;
  226. margin-block-end: 1em;
  227. margin-inline-start: 0px;
  228. margin-inline-end: 0px;
  229. margin-bottom: 1em !important;
  230. font-weight: bold;
  231. unicode-bidi: isolate;
  232. font-family: "CustomTitleFont";
  233. }
  234. p {
  235. display: block;
  236. margin-block-start: 1em;
  237. margin-block-end: 1em;
  238. margin-inline-start: 0px;
  239. margin-inline-end: 0px;
  240. unicode-bidi: isolate;
  241. }
  242. ul {
  243. display: block;
  244. list-style-type: disc;
  245. margin-block-start: 1em;
  246. margin-block-end: 1em;
  247. margin-inline-start: 0px;
  248. margin-inline-end: 0px;
  249. padding-inline-start: 40px;
  250. unicode-bidi: isolate;
  251. li {
  252. display: list-item;
  253. text-align: -webkit-match-parent;
  254. unicode-bidi: isolate;
  255. }
  256. }
  257. ol {
  258. list-style-type: decimal;
  259. display: block;
  260. list-style-type: decimal;
  261. margin-block-start: 1em;
  262. margin-block-end: 1em;
  263. margin-inline-start: 0px;
  264. margin-inline-end: 0px;
  265. padding-inline-start: 40px;
  266. unicode-bidi: isolate;
  267. }
  268. }
  269. }
  270. .custom-main{
  271. background: url('~/assets/images/swiper_bg.png') no-repeat center center;
  272. background-size: cover;
  273. width: 300px;
  274. height: 190px;
  275. }
  276. </style>